home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 23 Character Animation / SkinnedMesh / SkinnedData.cpp < prev    next >
C/C++ Source or Header  |  2016-03-02  |  5KB  |  180 lines

  1. #include "SkinnedData.h"
  2.  
  3. using namespace DirectX;
  4.  
  5. Keyframe::Keyframe()
  6.     : TimePos(0.0f),
  7.     Translation(0.0f, 0.0f, 0.0f),
  8.     Scale(1.0f, 1.0f, 1.0f),
  9.     RotationQuat(0.0f, 0.0f, 0.0f, 1.0f)
  10. {
  11. }
  12.  
  13. Keyframe::~Keyframe()
  14. {
  15. }
  16.  
  17. float BoneAnimation::GetStartTime()const
  18. {
  19.     // Keyframes are sorted by time, so first keyframe gives start time.
  20.     return Keyframes.front().TimePos;
  21. }
  22.  
  23. float BoneAnimation::GetEndTime()const
  24. {
  25.     // Keyframes are sorted by time, so last keyframe gives end time.
  26.     float f = Keyframes.back().TimePos;
  27.  
  28.     return f;
  29. }
  30.  
  31. void BoneAnimation::Interpolate(float t, XMFLOAT4X4& M)const
  32. {
  33.     if( t <= Keyframes.front().TimePos )
  34.     {
  35.         XMVECTOR S = XMLoadFloat3(&Keyframes.front().Scale);
  36.         XMVECTOR P = XMLoadFloat3(&Keyframes.front().Translation);
  37.         XMVECTOR Q = XMLoadFloat4(&Keyframes.front().RotationQuat);
  38.  
  39.         XMVECTOR zero = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
  40.         XMStoreFloat4x4(&M, XMMatrixAffineTransformation(S, zero, Q, P));
  41.     }
  42.     else if( t >= Keyframes.back().TimePos )
  43.     {
  44.         XMVECTOR S = XMLoadFloat3(&Keyframes.back().Scale);
  45.         XMVECTOR P = XMLoadFloat3(&Keyframes.back().Translation);
  46.         XMVECTOR Q = XMLoadFloat4(&Keyframes.back().RotationQuat);
  47.  
  48.         XMVECTOR zero = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
  49.         XMStoreFloat4x4(&M, XMMatrixAffineTransformation(S, zero, Q, P));
  50.     }
  51.     else
  52.     {
  53.         for(UINT i = 0; i < Keyframes.size()-1; ++i)
  54.         {
  55.             if( t >= Keyframes[i].TimePos && t <= Keyframes[i+1].TimePos )
  56.             {
  57.                 float lerpPercent = (t - Keyframes[i].TimePos) / (Keyframes[i+1].TimePos - Keyframes[i].TimePos);
  58.  
  59.                 XMVECTOR s0 = XMLoadFloat3(&Keyframes[i].Scale);
  60.                 XMVECTOR s1 = XMLoadFloat3(&Keyframes[i+1].Scale);
  61.  
  62.                 XMVECTOR p0 = XMLoadFloat3(&Keyframes[i].Translation);
  63.                 XMVECTOR p1 = XMLoadFloat3(&Keyframes[i+1].Translation);
  64.  
  65.                 XMVECTOR q0 = XMLoadFloat4(&Keyframes[i].RotationQuat);
  66.                 XMVECTOR q1 = XMLoadFloat4(&Keyframes[i+1].RotationQuat);
  67.  
  68.                 XMVECTOR S = XMVectorLerp(s0, s1, lerpPercent);
  69.                 XMVECTOR P = XMVectorLerp(p0, p1, lerpPercent);
  70.                 XMVECTOR Q = XMQuaternionSlerp(q0, q1, lerpPercent);
  71.  
  72.                 XMVECTOR zero = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
  73.                 XMStoreFloat4x4(&M, XMMatrixAffineTransformation(S, zero, Q, P));
  74.  
  75.                 break;
  76.             }
  77.         }
  78.     }
  79. }
  80.  
  81. float AnimationClip::GetClipStartTime()const
  82. {
  83.     // Find smallest start time over all bones in this clip.
  84.     float t = MathHelper::Infinity;
  85.     for(UINT i = 0; i < BoneAnimations.size(); ++i)
  86.     {
  87.         t = MathHelper::Min(t, BoneAnimations[i].GetStartTime());
  88.     }
  89.  
  90.     return t;
  91. }
  92.  
  93. float AnimationClip::GetClipEndTime()const
  94. {
  95.     // Find largest end time over all bones in this clip.
  96.     float t = 0.0f;
  97.     for(UINT i = 0; i < BoneAnimations.size(); ++i)
  98.     {
  99.         t = MathHelper::Max(t, BoneAnimations[i].GetEndTime());
  100.     }
  101.  
  102.     return t;
  103. }
  104.  
  105. void AnimationClip::Interpolate(float t, std::vector<XMFLOAT4X4>& boneTransforms)const
  106. {
  107.     for(UINT i = 0; i < BoneAnimations.size(); ++i)
  108.     {
  109.         BoneAnimations[i].Interpolate(t, boneTransforms[i]);
  110.     }
  111. }
  112.  
  113. float SkinnedData::GetClipStartTime(const std::string& clipName)const
  114. {
  115.     auto clip = mAnimations.find(clipName);
  116.     return clip->second.GetClipStartTime();
  117. }
  118.  
  119. float SkinnedData::GetClipEndTime(const std::string& clipName)const
  120. {
  121.     auto clip = mAnimations.find(clipName);
  122.     return clip->second.GetClipEndTime();
  123. }
  124.  
  125. UINT SkinnedData::BoneCount()const
  126. {
  127.     return mBoneHierarchy.size();
  128. }
  129.  
  130. void SkinnedData::Set(std::vector<int>& boneHierarchy, 
  131.                       std::vector<XMFLOAT4X4>& boneOffsets,
  132.                       std::unordered_map<std::string, AnimationClip>& animations)
  133. {
  134.     mBoneHierarchy = boneHierarchy;
  135.     mBoneOffsets   = boneOffsets;
  136.     mAnimations    = animations;
  137. }
  138.  
  139. void SkinnedData::GetFinalTransforms(const std::string& clipName, float timePos,  std::vector<XMFLOAT4X4>& finalTransforms)const
  140. {
  141.     UINT numBones = mBoneOffsets.size();
  142.  
  143.     std::vector<XMFLOAT4X4> toParentTransforms(numBones);
  144.  
  145.     // Interpolate all the bones of this clip at the given time instance.
  146.     auto clip = mAnimations.find(clipName);
  147.     clip->second.Interpolate(timePos, toParentTransforms);
  148.  
  149.     //
  150.     // Traverse the hierarchy and transform all the bones to the root space.
  151.     //
  152.  
  153.     std::vector<XMFLOAT4X4> toRootTransforms(numBones);
  154.  
  155.     // The root bone has index 0.  The root bone has no parent, so its toRootTransform
  156.     // is just its local bone transform.
  157.     toRootTransforms[0] = toParentTransforms[0];
  158.  
  159.     // Now find the toRootTransform of the children.
  160.     for(UINT i = 1; i < numBones; ++i)
  161.     {
  162.         XMMATRIX toParent = XMLoadFloat4x4(&toParentTransforms[i]);
  163.  
  164.         int parentIndex = mBoneHierarchy[i];
  165.         XMMATRIX parentToRoot = XMLoadFloat4x4(&toRootTransforms[parentIndex]);
  166.  
  167.         XMMATRIX toRoot = XMMatrixMultiply(toParent, parentToRoot);
  168.  
  169.         XMStoreFloat4x4(&toRootTransforms[i], toRoot);
  170.     }
  171.  
  172.     // Premultiply by the bone offset transform to get the final transform.
  173.     for(UINT i = 0; i < numBones; ++i)
  174.     {
  175.         XMMATRIX offset = XMLoadFloat4x4(&mBoneOffsets[i]);
  176.         XMMATRIX toRoot = XMLoadFloat4x4(&toRootTransforms[i]);
  177.         XMMATRIX finalTransform = XMMatrixMultiply(offset, toRoot);
  178.         XMStoreFloat4x4(&finalTransforms[i], XMMatrixTranspose(finalTransform));
  179.     }
  180. }